<?php

namespace app\api\controller\ai;

use app\common\controller\Api;
use app\api\service\DeepseekHelper;
use think\Env;
use think\Exception;
use think\exception\ThrowableError;
use think\Log;

class demo extends Api
{
    protected $noNeedLogin = ['*']; //本地无需登录 线上可移除强制登录状态下访问
    protected $noNeedRight = ['*'];


    private const BASE_URL = 'https://api.deepseek.com'; //通用网关

    private const BASE_OPENAI_URL = 'https://api.deepseek.com/v1'; //出于与 OpenAI 兼容考虑

    private $buffer = '';
    private $partialChar = '';

    public function create()
    {
        return '123213122';
    }

    /**
     * 情感机器学习.
     * @throws \think\exception\DbException
     */
    public function generate(){
        $msg = $this->request->post('messages');
        if(!$msg){
            $this->error('messages params is require');
        }
        if(mb_strlen($msg, "UTF-8") > 50){
            $this->error('发送消息不能超过五十个字');
        }
        //$data['result'] = DeepseekHelper::balance();
        //DeepseekHelper::getAiGeneratedEmotionMsgByStream($msg);
        try {
            $data['result'] = DeepseekHelper::getAiGeneratedArticleNewByWords($msg);
            $this->success('success',$data);
        }catch (ThrowableError $e){
            $this->success($e->getMessage(),['result'=>'等我们成为朋友我再告诉你吧~']);
        }catch (Exception $e){
            $this->success($e->getMessage(),['result'=>'等我们成为朋友我再告诉你吧~']);
        }
        $this->error('网络频繁,请稍后再试');
    }


    /**
     * 情感对话流式输出.
     * @throws \think\exception\DbException
     */
    public function stream()
    {
        $words = $this->request->param('messages');
        if(!$words){
            $this->error('对话消息必须');
        }
        if(mb_strlen($words, "UTF-8") > 50){
            $this->error('发送消息不能超过五十个字');
        }

        // 设置请求头
        $headers = [
            'Content-Type: application/json',
            'Authorization: Bearer '.Env::get('deepSeek.apikey'),
        ];

        $prompt = "
        在交友软件中,({$words})这是男生和你说的话,请你模拟在交友软件中的女生和我对话,并按以下要求回答。
        1.友好互动，希望得到积极的回应和情感支持，需要充满温暖和关怀。
        2.回答内容不能带特殊字符、表情符号等。
        3.回答内容不得超过50个字,并符合社交逻辑文字输出。
        4.回复内容不要包含男生的话({$words}),并控制在10秒内响应输出。
        5.回答内容，模拟真人聊天，保持自然，积极健康，确保没有歧义或不当内容。
        6.确保回答符合社交礼仪，既不过于冷淡也不过于主动，保持适当的距离感和友好态度。
        7.以女生暧昧、温暖的情感口吻回复,同时保持适当的幽默感，让对话更加轻松愉快。
        8.相同的({$words})每次连续回复需要不一样的内容。
        9.不要解释或解读我的上述场景描述和要求,请以一个女生口吻回复即可。
        10.({$words})如果包含隐私或不健康的话,可以回复：等我们成为朋友了我再告诉你吧。
        ";


        // 初始化cURL
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, self::BASE_URL.'/chat/completions');
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
            'model' => 'deepseek-chat',
            'messages' => [
                ['role'=> 'user','content'=> $prompt]
            ],
            'stream' => true
        ]));
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, false);
        curl_setopt($ch, CURLOPT_WRITEFUNCTION, function($ch, $data) {
            echo $data;
            ob_flush();
            flush();
            return strlen($data);
            //$this->processChunk($data);
            //return strlen($data);
        });

        // 在curl_exec之前添加
        curl_setopt($ch, CURLOPT_HEADERFUNCTION, function($ch, $header) use (&$statusCode) {
            if(preg_match('/HTTP\/\d\.\d (\d+)/', $header, $matches)){
                $statusCode = $matches[1];
            }
            return strlen($header);
        });

        // 执行请求
        curl_exec($ch);
        // 在curl_exec之后添加
        if ($statusCode >= 400) {
            $errorMsg = json_encode([
                'error' => [
                    'message' => "API请求失败 (状态码: $statusCode)",
                    'type' => 'http_error'
                ]
            ]);
            echo "data: $errorMsg\n\n";
            ob_flush();
            flush();
        }

        if(curl_errno($ch)) {
            echo "data: [ERROR] ".curl_error($ch)."\n\n";
            ob_flush();
            flush();
        }
        curl_close($ch);
    }

    private function processChunk($data) {
        $this->buffer .= $data;

        // 多字节安全分割
        while (preg_match('/\G(.*?\n)/us', $this->buffer, $matches, PREG_OFFSET_CAPTURE)) {
            $line = $matches[1][0];
            $this->emitLine($line);
            $this->buffer = substr($this->buffer, strlen($line));
        }
    }

    private function emitLine($line) {
        // 验证JSON完整性
        if (strpos($line, 'data: ') === 0) {
            $jsonPart = substr($line, 6);
            if (json_decode($jsonPart) !== null) {
                echo $line;
                ob_flush();
                flush();
                return;
            }
        }

        // 缓存不完整行
        $this->partialChar .= $line;
        if (!empty(substr($this->partialChar, 6)) && json_decode(substr($this->partialChar, 6))) {
            echo $this->partialChar;
            ob_flush();
            flush();
            $this->partialChar = '';
        }
    }

    private function flushRemaining() {
        if (!empty($this->partialChar)) {
            echo $this->partialChar."\n";
            ob_flush();
            flush();
        }
        echo "data: [DONE]\n\n";
        ob_flush();
        flush();
    }
}